package logic

import (
	"core/command"
	"core/common"
	"core/component/logger"
	"core/logic/logicredis"
	"encoding/json"
	"time"
)

// 玩家登陆
func (cli *Client) playerLoginHandler(msgId uint16, data []byte) {
	msgRecv := &command.CSPlayerLogin{}
	err := cli.router.UnMarshal(data, msgRecv)
	if err != nil {
		logger.Errorf("recv data:%v msg:%v", data, msgRecv)
		return
	}
	playerId, isNew, ret := cli.isSuccessLogin(msgRecv)
	if ret != command.NoticeType_Success {
		return
	}
	onlineServer := onlineServerMgrGetMe().getBestOnlineEndpoint()
	if onlineServer == nil {
		return
	}
	cli.onUserVerify(playerId)
	cli.bindOnline = true
	cli.joinOnlineID = onlineServer.srvID
	cli.sendClientOnlineMsg(onlineServer.srvID, isNew, msgRecv.IsVisitor)
	logger.Infof("玩家(%v)进入online", playerId)
}

func (cli *Client) isSuccessLogin(msgRecv *command.CSPlayerLogin) (uint64, bool, command.NoticeType) {
	var (
		playerId uint64
		isNew    bool
		ret      command.NoticeType
	)
	if !msgRecv.IsVisitor {
		playerId, isNew, ret = findPlayerIdByAccount(msgRecv.Account, msgRecv.Password)
	} else {
		playerId = common.StartUserid + logicredis.GenUuid()
		isNew = true
	}
	if logicredis.CacheRedis().Exists(common.MakePlayerIsOnline(playerId)).Val() == 1 {
		ret = command.NoticeType_AlreadyOnline
	}
	if ret != command.NoticeType_Success {
		msgSend := &command.SCPlayerLoginInfo{
			Ret: ret,
		}
		cli.sendMsg(command.Command_SCPlayerLoginInfo_Gateway, msgSend)
		return 0, false, ret
	}
	return playerId, isNew, command.NoticeType_Success
}

func findPlayerIdByAccount(account, password string) (uint64, bool, command.NoticeType) {
	info := &common.AccountInfo{}
	if logicredis.CacheRedis().Exists(common.MakeAccountKey(account)).Val() == 1 {
		bytes, err := logicredis.CacheRedis().Get(common.MakeAccountKey(account)).Bytes()
		if err != nil {
			return 0, false, command.NoticeType_AccountPasswordError
		}
		json.Unmarshal(bytes, info)
		if info.PassWord != password {
			return 0, false, command.NoticeType_AccountPasswordError
		}
		return info.Uid, false, command.NoticeType_Success
	} else {
		info.Uid = common.StartUserid + logicredis.GenUuid()
		info.PassWord = password
		bytes, _ := json.Marshal(info)
		logicredis.CacheRedis().Set(common.MakeAccountKey(account), bytes, 0)
		return info.Uid, true, command.NoticeType_Success
	}
}

func playerIsOnline(uid uint64) command.NoticeType {
	v, _ := logicredis.CacheRedis().Get(common.MakePlayerIsOnline(uid)).Int()
	if v == 1 {
		return command.NoticeType_AlreadyOnline
	}
	return command.NoticeType_Success
}

// 登出
func (cli *Client) playerLogoutHandler(msgId uint16, data []byte) {
	msgRecv := &command.CSPlayerLogout{}
	err := cli.router.UnMarshal(data, msgRecv)
	if err != nil {
		logger.Errorf("recv data:%v msg:%v", data, msgRecv)
		return
	}
	logicredis.CacheRedis().Del(common.MakePlayerIsOnline(cli.userID))
	if cli.joinOnlineID != "" {
		msgSend := &command.ClientOutOnline{
			PlayerId: cli.userID,
		}
		onlineServerMgrGetMe().sendMsgToOnlineServer(cli.joinOnlineID, command.Command_ClientOutOnline_Online, msgSend)
		logger.Infof("玩家:%v 登出onlineServer:%v", cli.userID, cli.joinOnlineID)
	}
	cli.clientLogout()
}

func (cli *Client) playerHeartBeat(msgId uint16, data []byte) {
	msgRecv := &command.CSHeartBeat{}
	err := cli.router.UnMarshal(data, msgRecv)
	if err != nil {
		logger.Errorf("recv data:%v msg:%v", data, msgRecv)
		return
	}
	msgSend := &command.SCHeartBeat{ServerTime: time.Now().UnixMilli()}
	cli.sendMsg(command.Command_SCHeartBeat_Gateway, msgSend)
}
